﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Web.Mvc;
using System.Collections;
using System.Text;

namespace Wicresoft.SMS.Web
{
    public class AuthorisedInputRender
    {
        private const string disabledstringunpostback = "disabled";
        private const string disabledstringpostback = "readonly";
        public static Dictionary<ControlType, Func<TagBuilder[]>> RenderMap =
            new Dictionary<ControlType, Func<TagBuilder[]>>()
            {
                { ControlType.button , RenderButtonControl },
                { ControlType.checkbox , RenderCheckBox },
                { ControlType.hidden ,  RenderButtonControl },
                { ControlType.label ,  RenderLabel },
                { ControlType.multi_select ,  RenderSelect },
                { ControlType.password ,  RenderTextControl },
                { ControlType.radio ,  RenderRadio },
                { ControlType.reset ,  RenderButtonControl },
                { ControlType.single_select ,  RenderSelect },
                { ControlType.submit ,  RenderButtonControl },
                { ControlType.text ,  RenderTextControl },
                { ControlType.textarea ,  RenderTextArea }
            };

        public static AuthorisedMetadataModel _model;


        public static TagBuilder[] RenderCheckBox()
        {
            if (_model == null)
                throw new NullReferenceException("_model should not be null");
            if(_model.PropertyValue == null)
                throw new NullReferenceException("Property value of _model should not be null");
            if (_model.PropertyValue.GetType().Name != "Boolean")
                throw new Exception("the property type is illegal , bool is expected. ");
            //checkbox itself and a hidden field will be built
            TagBuilder[] builders = new TagBuilder[2];

            TagBuilder tag = new TagBuilder("input");
            tag.MergeAttribute("type", "checkbox");
            tag.MergeAttribute("id", _model.Binding);
            tag.MergeAttribute("name", _model.Binding);
            tag.MergeAttribute("value", "true");
            tag.SetInnerText(_model.Display);
            if ((bool)_model.PropertyValue){
                tag.MergeAttribute("checked", "checked");
            }

            TagBuilder taghidden;
            //cause disabled checkbox will not post back , so the hidden field should do the post
            if (!_model.GetAuthoriseProvider().IsEnable){
                tag.MergeAttribute(disabledstringunpostback, disabledstringunpostback);
                taghidden = CreateHiddenField(_model.Binding, _model.PropertyValue.ToString());
            }
            else{
                taghidden = CreateHiddenField(_model.Binding, "false"); 
            }


            builders[0] = tag;
            builders[1] = taghidden;

            return builders;

        }

        public static TagBuilder[] RenderRadio()
        {
            if (_model == null)
                throw new NullReferenceException("_model should not be null");
            if (_model.PropertyValue == null)
                throw new NullReferenceException("Property value of _model should not be null");
            if (_model.PropertyValue.GetType().Name != "Boolean")
                throw new Exception("the property type is illegal , bool is expected. ");
            //checkbox itself and a hidden field will be built
            TagBuilder[] builders = new TagBuilder[2];

            TagBuilder tag = new TagBuilder("input");
            tag.MergeAttribute("type", "radio");
            tag.MergeAttribute("id", _model.Binding);
            tag.MergeAttribute("name", _model.Binding);
            tag.MergeAttribute("value", "true");
            tag.SetInnerText(_model.Display);
            if ((bool)_model.PropertyValue){
                tag.MergeAttribute("checked", "checked");
            }

            if (!_model.GetAuthoriseProvider().IsEnable)
            {
                tag.MergeAttribute(disabledstringunpostback, disabledstringunpostback);
                //since radio is grouped , only disabled and checked radio should use hidden to post back , others not
                if ((bool)_model.PropertyValue){
                    TagBuilder taghidden = CreateHiddenField(_model.Binding, "true");
                    builders[1] = taghidden;
                }
            }
            builders[0] = tag;

            return builders;
        }

        public static TagBuilder[] RenderTextArea()
        {
            if (_model == null)
                throw new NullReferenceException("_model should not be null");

            TagBuilder[] builders = new TagBuilder[2];

            TagBuilder tag = new TagBuilder("textarea");
            tag.MergeAttribute("id", _model.Binding);
            tag.MergeAttribute("name", _model.Binding);
            tag.SetInnerText(_model.Display);

            if (!_model.GetAuthoriseProvider().IsEnable){
                tag.MergeAttribute(disabledstringunpostback, disabledstringunpostback);
                //since use "disabled" the browser will not post back the field , so a hidden field should build here
                TagBuilder taghidden = CreateHiddenField(_model.Binding, _model.Display);
                builders[1] = taghidden;
            }

            builders[0] = tag;

            return builders;
        }

        public static TagBuilder[] RenderLabel()
        {
            if (_model == null)
                throw new NullReferenceException("_model should not be null");

            TagBuilder[] builders = new TagBuilder[1];

            TagBuilder tag = new TagBuilder("label");
            tag.SetInnerText(_model.Display);
            tag.MergeAttribute("for", _model.PropertyName);
            builders[0] = tag;

            return builders;
        }

        public static TagBuilder[] RenderSelect()
        {
            if (_model == null)
                throw new NullReferenceException("_model should not be null");
            IEnumerable<SelectListItem> listvalues = _model.PropertyValue as IEnumerable<SelectListItem>;
            if (listvalues == null)
                throw new Exception("the select element is not surpport the property which is not IEnumerable<SelectListItem> , SelectList or MultiSelectList can be used!");
            TagBuilder[] builders = new TagBuilder[2];

            TagBuilder tag = new TagBuilder("select");
            tag.MergeAttribute("id", _model.Binding);
            tag.MergeAttribute("name", _model.Binding);
            if (_model.ControlType == ControlType.multi_select){
                tag.MergeAttribute("multiple", "multiple");
            }

            StringBuilder sb = new StringBuilder();
            string selectedValue = string.Empty;
            foreach (var item in listvalues)
            {
                TagBuilder inneroption = new TagBuilder("option");
                inneroption.MergeAttribute("value", item.Value,true);
                inneroption.SetInnerText(item.Text);
                if (item.Selected){
                    inneroption.MergeAttribute("selected", "selected");
                    selectedValue = item.Value;
                }
                sb.Append(inneroption.ToString());
            }

            tag.InnerHtml = sb.ToString();
            
            if (!_model.GetAuthoriseProvider().IsEnable){
                tag.MergeAttribute(disabledstringunpostback, disabledstringunpostback);
                TagBuilder taghidden = CreateHiddenField(_model.Binding, selectedValue);
                builders[1] = taghidden;
            }

            builders[0] = tag;
            return builders;
        }

        public static TagBuilder[] RenderTextControl()
        {
            if (_model == null)
                throw new NullReferenceException("_model should not be null");
            TagBuilder[] builders = new TagBuilder[2];
            TagBuilder tag = new TagBuilder("input");
            tag.MergeAttribute("type", _model.ControlType.ToString());
            tag.MergeAttribute("id", _model.Binding);
            tag.MergeAttribute("name", _model.Binding);
            tag.MergeAttribute("value", _model.Display);
            if (!_model.GetAuthoriseProvider().IsEnable){
                tag.MergeAttribute(disabledstringunpostback, disabledstringunpostback);
                TagBuilder taghidden = CreateHiddenField(_model.Binding, _model.Display);
                builders[1] = taghidden;
            }

            builders[0] = tag;

            return builders;
        }

        public static TagBuilder[] RenderButtonControl()
        {
            if (_model == null)
                throw new NullReferenceException("_model should not be null");
            TagBuilder[] builders = new TagBuilder[1];
            TagBuilder tag = new TagBuilder("input");
            tag.MergeAttribute("type", _model.ControlType.ToString());
            tag.MergeAttribute("id", _model.PropertyName);
            tag.MergeAttribute("name", _model.PropertyName);
            tag.MergeAttribute("value", _model.Display);
            if (!_model.GetAuthoriseProvider().IsEnable){
                tag.MergeAttribute(disabledstringunpostback, disabledstringunpostback);
            }

            builders[0] = tag;

            return builders;
        }

        private static TagBuilder CreateHiddenField(string name,string value)
        {
            TagBuilder hidden = new TagBuilder("input");
            hidden.MergeAttribute("type","hidden");
            hidden.MergeAttribute("name", name);
            hidden.MergeAttribute("value", value);
            return hidden;
        }

    }
}